#region Header
//=============================================================================
//                          GShield (Game Shield)
//=============================================================================
//
// Original Programmer: Shawn Jackson
// Company: WaveTech Digital Technologies, Inc. (http://www.wtdt.com)
// Copyright: (c) 2006 WaveTech Digital Technologies, Inc. All Rights Reserved.
// Assembly: Engine
// Code File Name: GameManager.cs
// Code File Date: 12/7/2006
//
// Code File Info: Game Management System
//=============================================================================
/*
 * UPDATES
 * -------
 *				 ShawnJ 5/5/2007 (0.9.0.x): Refactoring for OSS.
 *				 ShawnJ 5/24/2007 (0.9.2.x): Changed LogDAO to Logging system.
 */
#endregion Header

#region License
/*
  GShield - Game Shield
  Copyright (C) 2006-2007 WaveTech Digital Technologies, Inc.
                                http://www.wtdt.com

  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/
#endregion License

#region Includes
using System;
using WaveTech.GShield.Data;
using WaveTech.GShield.Engine.Systems;
using WaveTech.GShield.Engine.Tools;
using WaveTech.GShield.Model;

#endregion Includes

namespace WaveTech.GShield.Engine.Managers
{
  public class GameManager
  {
    #region Singleton
		// Note, a Singleton is used instead of a static, or class static 
		// beacuse the locking in GetGame() does not work with statics.
    static readonly GameManager instance = new GameManager();
    #endregion Singleton

    #region Private Members

    #endregion Private Members

    #region Constructors
    // Explicit static constructor to tell C# compiler
    // not to mark type as beforefieldinit
    static GameManager()
    {
    }

    GameManager()
    {
      
    }
    #endregion Constructors

    #region Instance Property
    public static GameManager Instance
    {
      get
      {
        return instance;
      }
    }
    #endregion Instance Property

    #region Get Game
		/// <summary>
		/// Gets a game object by querying the internal system with details about the game.
		/// </summary>
		/// <param name="p">GameProcess object used to pull game information</param>
		/// <param name="fullPath">Full file path to the executable</param>
		/// <param name="internalName">Files internal name</param>
		/// <param name="productName">Files product name</param>
		/// <param name="company">Files company</param>
		/// <param name="fileName">Name of the file</param>
		/// <returns>Populated game object, if game is found, else null</returns>
    public Game GetGame(GameProcess p, string fullPath, string internalName, string productName, string company, string fileName)
    {
      Game g = null;
      
      lock (this)
      {
				if (GamesDAO.GetGameByPath(fullPath) != null)
        {	// Get game data by it's path
					g = GamesDAO.GetGameByPath(fullPath);
        }

        if (g == null && (productName != null && company != null))  
        { // Path should work, but if it was moved, get by internal stuff
					g = GamesDAO.GetGameByProductNameCompany(productName, company);
        }

				if (g == null)
				{	// Gets a game by the directory, for directory only games.
					g = GamesDAO.GetGameByPath(StringTools.GetDirectoryPath(fullPath));
				}

        if ((g != null) && (g.RatingType == null))
        {	// Game doesn't have a rating, get the rating from the Advisor Service
					RatingTypes rating;
          Advisor advisor = new Advisor();
          
          if (p != null)
            rating = advisor.GetESRBRating(p.InternalName, p.Company, StringTools.GetFileName(p.Process.MainModule.FileName), StringTools.GetDirectoryName(p.Process.MainModule.FileName, true), p.ProductName);
          else
            rating = advisor.GetESRBRating(internalName, company, StringTools.GetFileName(fullPath), StringTools.GetDirectoryName(fullPath, true), productName);

          g.RatingType = (int)rating;
          
          if (g.Content == null || g.Platforms == null || g.Publisher == null || g.Rating == null)
          {
            if (rating != RatingTypes.Unknown)
            {
							GameRatingDetail detail;

              if (p != null)
								//TODO: Change to Azure web service
								//detail = advisor.GetESRBGameDetail(p.InternalName, p.Company, StringTools.GetFileName(p.Process.MainModule.FileName), StringTools.GetDirectoryName(p.Process.MainModule.FileName, true), p.ProductName);
								detail = null;
							else
							//TODO: Change to Azure web service	
							//detail = advisor.GetESRBGameDetail(internalName, company, StringTools.GetFileName(fullPath), StringTools.GetDirectoryName(fullPath, true), productName);
            	detail = null;

              g.WasChecked = true;
              g.Content = detail.Content;
              g.Platforms = detail.Platforms;
              g.Publisher = detail.Publisher;
              g.Rating = detail.Rating;
            }
          }

          GamesDAO.Save(g);
        }

        if (g != null /* && !g.IsHashValid() */)
        {	// If the games Hash is not valid new data should be pulled down to fix the stored game data
					Logging.Write("A Game (" + g.Name + ") hash is invalid, Id = " + g.Id, LogCategory.Games, LogPriority.Low, LogType.GameInvalid);

					if (g.WasChecked.HasValue && g.WasChecked.Value) // It recieved information from the WebService and was not manually added.
          {
						RatingTypes rating;
            Advisor advisor = new Advisor();

            rating = advisor.GetESRBRating(internalName, company, StringTools.GetFileName(fullPath), StringTools.GetDirectoryName(fullPath, true), productName);

            g.RatingType = (int)rating;

            if (rating != RatingTypes.Unknown)
            {
							//TODO: Convert to Azure web service.
							//GameRatingDetail detail = advisor.GetESRBGameDetail(internalName, company, StringTools.GetFileName(fullPath), StringTools.GetDirectoryName(fullPath, true), productName);
            	GameRatingDetail detail = null;

              g.WasChecked = true;
              g.DateChecked = DateTime.Now;
              g.Content = detail.Content;
              g.Platforms = detail.Platforms;
              g.Publisher = detail.Publisher;
              g.Rating = detail.Rating;
            }

            GamesDAO.Save(g);
          }
        }

        if (g == null)
        {	// Get the game from the ESRB's web site.
					RatingTypes rating;
          Advisor advisor = new Advisor();
          GameRatingDetail detail = null;

          rating = advisor.GetESRBRating(internalName, company, StringTools.GetFileName(fullPath), StringTools.GetDirectoryName(fullPath, true), productName);

					if (rating != RatingTypes.Unknown)
						//TODO: Convert to Azure web service
						//detail = advisor.GetESRBGameDetail(internalName, company, StringTools.GetFileName(fullPath), StringTools.GetDirectoryName(fullPath, true), productName);
						detail = null;

					if (p != null)
					{
						g = new Game();
						g.Company = p.Company;
						g.FileName = p.FullPath;
						g.InternalName = p.InternalName;
						g.ProductName = p.ProductName;
						g.Content = detail.Content;
						g.Name = detail.Name;
						g.Platforms = detail.Platforms;
						g.Publisher = detail.Publisher;
						g.Rating = detail.Rating;
						g.RatingType = (int)rating;
						g.DirectoryName = StringTools.GetDirectoryName(fullPath, true);
						g.FileName = StringTools.GetFileName(fullPath);
					}
					else
					{
						g = new Game();
						g.Company = company;
						g.FileName = fullPath;
						g.InternalName = internalName;
						g.ProductName = productName;
						g.Content = detail.Content;
						g.Name = detail.Name;
						g.Platforms = detail.Platforms;
						g.Publisher = detail.Publisher;
						g.Rating = detail.Rating;
						g.RatingType = (int)rating;
						g.DirectoryName = StringTools.GetDirectoryName(fullPath, true);
						g.FileName = StringTools.GetFileName(fullPath);
					}

          GamesDAO.Save(g);

					Logging.Write("A new Game (" + g.Name + ") has been acquired and saved, Id = " + g.Id, LogCategory.Games, LogPriority.Low, LogType.GameNew);
        }
      }
      return g;
    }
    #endregion Get Game
  }
}